/*
 * BZPController.cpp
 *
 *  Created on: 24/05/2014
 *      Author: javier
 */

#include "BZPController.h"
#include "Utils.h"
#include <iostream>

BZPController::BZPController(BZPView* view, BZPModel* model,
		ClientSocket& socket, ClientSocket& socketReceptor) :
		sender(this, socket), listener(this, socketReceptor) {
	this->view = view;
	this->model = model;
	running = false;
}

void BZPController::mainLoop() {
	running = true;
	SDL_Event e;
	sender.init();
	if (sender.isConnected()) {
		listener.init();
		sender.start();
		listener.start();
	}
	while (running) {
		while (SDL_PollEvent(&e)) {
			switch (e.type) {
			case SDL_QUIT:
				running = false;
				break;
			case SDL_KEYDOWN:
				switch (e.key.keysym.sym) {
				case SDLK_w:
					if (model->validate(MOVE_UP))
						sender.sendMovementUp();
					break;
				case SDLK_s:
					if (model->validate(MOVE_DOWN))
						sender.sendMovementDown();
					break;
				case SDLK_a:
					if (model->validate(MOVE_LEFT))
						sender.sendMovementLeft();
					break;
				case SDLK_d:
					if (model->validate(MOVE_RIGHT))
						sender.sendMovementRight();
					break;
				case SDLK_SPACE:
					sender.sendDropBomb();
					break;
				case SDLK_ESCAPE:
					running = false;
					break;
				default:
					break;
				}
				break;
			case SDL_MOUSEMOTION:
				if (e.motion.state == SDL_PRESSED) {
					// Arrastrando un elemento en pantalla
					printf("Dragging %d from %d,%d to (%d,%d)\n",
							e.button.button, e.motion.xrel, e.motion.yrel,
							e.motion.x, e.motion.y);
				}
				break;
			case SDL_MOUSEBUTTONDOWN:
				// Clic simple en pantalla
//				printf("Mouse button %d pressed at (%d,%d)\n", e.button.button,
//						e.button.x, e.button.y);
				view->handleClick(e.button.x, e.button.y);
				break;
			}
		}
		mutex.lock();
		view->update();
		view->render();
		mutex.unlock();
		SDL_Delay(150);
	}
}

void BZPController::updatePosition(int id, double x, double y) {
	mutex.lock();
	model->update(id, x, y);
	mutex.unlock();
}

void BZPController::newObject(Positionable *p) {
	mutex.lock();
	std::cout << "Nuevo objeto: " << p->getId() << " " << p->getX() << " "
			<< p->getY() << std::endl;
	Positionable* object = model->add(p);
	view->add(object);
	sound.playEvent(p, NEW_OBJECT);
	mutex.unlock();
}

void BZPController::removeObject(int id) {
	Positionable* object = model->getObject(id);
	if (!object)
		return;
	mutex.lock();
	if (model->getTarget() != NULL && id == model->getTarget()->getId()) {
		model->setIDTarget(-1);
		view->setTarget(NULL);
	}
	model->remove(id);
	view->removeView(id);
	view->addExplosionView(object);
	sound.playEvent(object, DESTROY_OBJECT);
	mutex.unlock();
}

void BZPController::joinGame() {
	view->clear();
	view->changeToView(MATCH_SELECT);
	sender.sendJoinGameMessage();
}

void BZPController::newGame() {
	view->clear();
	view->changeToView(GAME_SELECT);
	sender.sendNewGameMessage();
}

void BZPController::setIDTarget(int id) {
	model->setIDTarget(id);
	view->setTarget(model->getTarget());
}

void BZPController::loadScenario(Scenario& s) {
	model->setDimensions(s.getWidth(), s.getHeight());
	view->setScenarioDimensions(s.getWidth(), s.getHeight());
	std::list<Positionable*> tiles = s.getTilesObjects();
	std::list<Positionable*>::iterator it;
	for (it=tiles.begin(); it != tiles.end();++it){
		newObject(*it);
	}
//	setIDTarget(s.getIdPlayer());
	// Para el envio de datos al servidor
	sender.setIdJugador(s.getIdPlayer());
	listener.setIdJugador(s.getIdPlayer());
	view->changeToView(GAME);
}

void BZPController::showCampaigns() {
	view->showCampaigns(campaigns);
}

void BZPController::showPartidas() {
	view->showPartidas(partidas);
}

void BZPController::showWaitingPlayers() {
	view->changeToView(WAITING);
}

void BZPController::decideStartGameView() {
	view->changeToView(DECIDE_GAME_START);
}

void BZPController::sendSelectCampaign(std::string& idCampania,
		std::string& nombrePartida) {
	view->clear();
	sender.sendSelectCampaign(idCampania, nombrePartida);
}

void BZPController::sendStartMatch(bool comenzar, string& idPartida) {
	view->clear();
	sender.sendStartMatch(comenzar, idPartida);
	if (comenzar == false) {
		view->changeToView(MENU);
	}
}

BZPController::~BZPController() {
	if (sender.isRunning()) {
		sender.stop();
		sender.cancel();
		sender.join();
	}
	if (listener.isRunning()) {
		listener.stop();
		listener.cancel();
		listener.join();
	}
}

void BZPController::exit() {
	running = false;
}

void BZPController::setCampaigns(const std::string& campaigns) {
	this->campaigns = campaigns;
}

void BZPController::showMainMenu() {
	view->clear();
	view->changeToView(MENU);
}

void BZPController::setPartidas(std::string partidas) {
	this->partidas = partidas;
}

void BZPController::sendSelectedMatch(std::string& idPartida) {
	view->clear();
	sender.sendSelectedMatch(idPartida);
}

void BZPController::showNextMatchView() {
	view->showInfo(NEXT_MATCH);
}

void BZPController::updateScores(std::string scores) {
	view->updateScore(scores);
}

void BZPController::clear() {
	view->clear();
	model->clear();
}

void BZPController::showEndCampaignView() {
	view->showInfo(END_GAME);
}

void BZPController::loadNextScenario() {
	sender.sendLoadNextScenario();
}

void BZPController::sendResetGameMessage() {
	view->clear();
	sender.sendResetGameMessage();
}
